//    Copyright (C) Kherty.  All rights reserved.
using System;

namespace OpenLS.Spreadsheet.StandardAddIn.Statistics
{
    internal class FDistribution : ContinuousDistribution
    {
        private double _firstDegreesOfFreedom;
        private double _secondDegreesOfFreedom;

        public FDistribution(double firstDegreesOfFreedom, double secondDegreesOfFreedom)
        {
            FirstDegreesOfFreedom = firstDegreesOfFreedom;
            SecondDegreesOfFreedom = secondDegreesOfFreedom;
        }

        public double FirstDegreesOfFreedom
        {
            get { return _firstDegreesOfFreedom; }
            set
            {
                if (value <= 0)
                    throw new ArgumentOutOfRangeException("value");
                _firstDegreesOfFreedom = value;
            }
        }

        public double SecondDegreesOfFreedom
        {
            get { return _secondDegreesOfFreedom; }
            set
            {
                if (value <= 0.0)
                    throw new ArgumentOutOfRangeException("value");
                _secondDegreesOfFreedom = value;
            }
        }

        public override double CumulativeProbability(double x)
        {
            if (x <= 0.0)
                return 0.0;
            return
                Statistician.RegularizedBeta(
                    (FirstDegreesOfFreedom*x)/(SecondDegreesOfFreedom + FirstDegreesOfFreedom*x),
                    FirstDegreesOfFreedom/2,
                    SecondDegreesOfFreedom/2);
        }

        public override double InverseCumulativeProbability(double probability)
        {
            if (probability == 0)
                return 0;
            if (probability == 1)
                return double.PositiveInfinity;
            return base.InverseCumulativeProbability(probability);
        }

        protected override SolverParameters GetSolverParameters(double probability)
        {
            return new SolverParameters(
                0, double.MaxValue,
                SecondDegreesOfFreedom < 2.2
                    ? 40
                    : SecondDegreesOfFreedom/
                      (SecondDegreesOfFreedom - 2.0));
        }
    }
}